package com.ikingtech.platform.service.log.controller;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ikingtech.framework.sdk.base.model.PageResult;
import com.ikingtech.framework.sdk.context.event.TenantDeleteEvent;
import com.ikingtech.framework.sdk.context.security.Me;
import com.ikingtech.framework.sdk.context.exception.FrameworkException;
import com.ikingtech.framework.sdk.core.response.R;
import com.ikingtech.framework.sdk.log.api.LogApi;
import com.ikingtech.framework.sdk.log.model.*;
import com.ikingtech.framework.sdk.log.model.rpc.AuthLogReportParam;
import com.ikingtech.framework.sdk.log.model.rpc.OperationLogReportParam;
import com.ikingtech.framework.sdk.log.model.rpc.SystemLogBatchReportParam;
import com.ikingtech.framework.sdk.utils.Tools;
import com.ikingtech.framework.sdk.web.annotation.ApiController;
import com.ikingtech.platform.service.log.entity.AuthLogDO;
import com.ikingtech.platform.service.log.entity.OperationLogDO;
import com.ikingtech.platform.service.log.entity.SystemLogDO;
import com.ikingtech.platform.service.log.service.AuthLogRepository;
import com.ikingtech.platform.service.log.service.OperationLogRepository;
import com.ikingtech.platform.service.log.service.SystemLogRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.context.event.EventListener;

import java.util.List;

/**
 * @author tie yan
 */
@RequiredArgsConstructor
@ApiController(value = "/log", name = "日志中心", description = "日志中心")
public class LogController implements LogApi {

    private final AuthLogRepository authLogRepo;

    private final OperationLogRepository operationLogRepo;

    private final SystemLogRepository systemLogRepo;

    /**
     * 报告认证日志
     * @param authLog 认证日志报告参数
     * @return 返回认证日志报告结果
     */
    @Override
    public R<Object> reportAuthLog(AuthLogReportParam authLog) {
        // 将认证日志报告参数转换为认证日志实体对象
        AuthLogDO entity = Tools.Bean.copy(authLog, AuthLogDO.class);
        // 生成认证日志ID
        entity.setId(Tools.Id.uuid());
        // 保存认证日志实体对象
        this.authLogRepo.save(entity);
        // 返回认证日志报告结果
        return R.ok();
    }

    /**
     * 删除授权日志
     * @param id 授权日志ID
     * @return 删除结果
     */
    @Override
    public R<Object> deleteAuthLog(String id) {
        // 调用authLogRepo的removeById方法删除指定ID的授权日志
        this.authLogRepo.removeById(id);
        // 返回删除成功的结果
        return R.ok();
    }

    /**
     * 分页查询授权日志
     * @param queryParam 查询参数
     * @return 返回授权日志列表
     */
    @Override
    public R<List<AuthLogDTO>> authLogPage(AuthLogQueryParamDTO queryParam) {
        return R.ok(PageResult.build(this.authLogRepo.page(new Page<>(queryParam.getPage(), queryParam.getRows()), AuthLogRepository.createWrapper(queryParam))).convert(entity -> {
            AuthLogDTO log = Tools.Bean.copy(entity, AuthLogDTO.class);
            if (null != log.getType()) {
                log.setTypeName(log.getType().description);
            }
            return log;
        }));
    }

    /**
     * 根据条件查询授权日志列表
     *
     * @param queryParam 查询参数
     * @return 查询结果
     */
    @Override
    public R<List<AuthLogDTO>> listAuthLogByConditions(AuthLogQueryParamDTO queryParam) {
        // 调用authLogRepo的list方法，传入AuthLogRepository.createWrapper(queryParam)作为参数
        // 将查询结果转换为AuthLogDTO列表
        return R.ok(Tools.Coll.convertList(this.authLogRepo.list(AuthLogRepository.createWrapper(queryParam)), entity -> {
            // 将实体转换为AuthLogDTO对象
            AuthLogDTO log = Tools.Bean.copy(entity, AuthLogDTO.class);
            // 如果log的type不为空，则设置log的typeName为type的description
            if (null != log.getType()) {
                log.setTypeName(log.getType().description);
            }
            return log;
        }));
    }

    /**
     * 报告操作日志
     * @param operationLog 操作日志参数
     * @return 操作结果
     */
    @Override
    public R<Object> reportOperationLog(OperationLogReportParam operationLog) {
        // 将操作日志参数转换为操作日志实体
        OperationLogDO entity = Tools.Bean.copy(operationLog, OperationLogDO.class);
        // 生成唯一ID
        entity.setId(Tools.Id.uuid());
        // 设置租户代码
        entity.setTenantCode(Me.tenantCode());
        // 保存操作日志实体到数据库
        this.operationLogRepo.save(entity);
        // 返回操作成功结果
        return R.ok();
    }

    /**
     * 删除操作日志
     * @param id 操作日志ID
     * @return 删除结果
     */
    @Override
    public R<Object> deleteOperationLog(String id) {
        // 从操作日志仓库中删除指定ID的操作日志
        this.operationLogRepo.removeById(id);
        return R.ok();
    }

    /**
     * 获取操作日志分页数据
     *
     * @param queryParam 查询参数
     * @return 操作日志分页数据
     */
    @Override
    public R<List<OperationLogDTO>> operationLogPage(OperationLogQueryParamDTO queryParam) {
        return R.ok(PageResult.build(this.operationLogRepo.page(new Page<>(queryParam.getPage(), queryParam.getRows()), OperationLogRepository.createWrapper(queryParam))).convert(entity -> Tools.Bean.copy(entity, OperationLogDTO.class)));
    }

    /**
     * 根据条件查询操作日志列表
     *
     * @param queryParam 查询参数
     * @return 操作日志列表
     */
    @Override
    public R<List<OperationLogDTO>> listOperationLogByConditions(OperationLogQueryParamDTO queryParam) {
        return R.ok(Tools.Coll.convertList(this.operationLogRepo.list(OperationLogRepository.createWrapper(queryParam)), entity -> Tools.Bean.copy(entity, OperationLogDTO.class)));
    }

    /**
     * 获取操作日志详情
     *
     * @param id 操作日志ID
     * @return 操作日志详情
     */
    @Override
    public R<OperationLogDTO> operationLogDetail(String id) {
        // 根据ID获取操作日志实体
        OperationLogDO entity = operationLogRepo.getById(id);
        // 如果实体为空，则抛出异常
        if (null == entity) {
            throw new FrameworkException("operationLogNotFound");
        }
        // 将实体转换为操作日志DTO并返回
        return R.ok(Tools.Bean.copy(entity, OperationLogDTO.class));
    }

    /**
     * 报告系统日志
     * @param systemLogs 系统日志批次报告参数
     * @return 报告结果
     */
    @Override
    public R<Object> reportSystemLog(SystemLogBatchReportParam systemLogs) {
        // 保存系统日志批次
        this.systemLogRepo.saveBatch(Tools.Coll.convertList(systemLogs.getLogReportParams(), log -> {
            // 创建系统日志实体
            SystemLogDO entity = Tools.Bean.copy(log, SystemLogDO.class);
            // 生成唯一ID
            entity.setId(Tools.Id.uuid());
            // 设置租户代码
            entity.setTenantCode(Me.tenantCode());
            return entity;
        }));
        // 返回成功结果
        return R.ok();
    }

    /**
     * 删除系统日志
     * @param id 系统日志ID
     * @return 删除结果
     */
    @Override
    public R<Object> deleteSystemLog(String id) {
        // 调用系统日志仓库的removeById方法删除指定ID的日志
        this.systemLogRepo.removeById(id);
        // 返回删除成功的结果
        return R.ok();
    }

    @Override
    public R<List<SystemLogDTO>> systemLogPage(SystemLogQueryParamDTO queryParam) {
        return R.ok(PageResult.build(this.systemLogRepo.page(new Page<>(queryParam.getPage(), queryParam.getRows()), SystemLogRepository.createWrapper(queryParam))).convert(entity -> Tools.Bean.copy(entity, SystemLogDTO.class)));
    }

    /**
     * 获取系统日志详情
     * @param id 系统日志ID
     * @return 系统日志详情
     */
    @Override
    public R<SystemLogDTO> systemLogDetail(String id) {
        // 通过ID获取系统日志实体
        SystemLogDO entity = this.systemLogRepo.getById(id);
        // 如果实体为空，则抛出异常
        if (null == entity) {
            throw new FrameworkException("systemLogNotFound");
        }
        // 将实体转换为系统日志DTO并返回
        return R.ok(Tools.Bean.copy(entity, SystemLogDTO.class));
    }

    @EventListener
    public void tenantDeleteEventListener(TenantDeleteEvent event) {
        this.operationLogRepo.remove(Wrappers.<OperationLogDO>query().lambda().eq(OperationLogDO::getTenantCode, event.getCode()));
        this.systemLogRepo.remove(Wrappers.<SystemLogDO>query().lambda().eq(SystemLogDO::getTenantCode, event.getCode()));
    }
}
